type File           native;  // rx.File
type FileReadOnly   protected File;
type FileWriteOnly  protected File;
type FileReadWrite  protected File;

type FileState {
    // rx.FileState
    name:     String,
    size:     Number,
    mode:     FileMode,
    is-dir:   Bool,
    mod-time: time::Time
};
type FileMode native;

export function walk-dir:
    &(Path) => Observable[(Path,FileState),Error]
    native 'walk-dir';

export function list-dir:
    &(Path) => Observable[(Path,FileState),Error]
    native 'list-dir';

// TODO: use consumer (File -> Async, close on complete) instead of open/close
export function open-read-only:
    &(Path) => Async[FileReadOnly,Error]
    native 'open-read-only';
export function open-read-write:
    &(Path) => Async[FileReadWrite,Error]
    native 'open-read-write';
export function open-read-write-create:
    &(Path) => Async[FileReadWrite,Error]
    native 'open-read-write-create';
export function open-overwrite:
    &(Path) => Async[FileWriteOnly,Error]
    native 'open-overwrite';
export function open-append:
    &(Path) => Async[FileWriteOnly,Error]
    native 'open-append';

export function close:
    &(File) => Async
    native 'file-close';

export function get-state:
    &(File) => Async[FileState,Error]
    native 'file-get-state';

export function read:
    &(FileReadOnly,Number) => Async[Bytes,Error]
    native 'file-read';
export function read:
    &(FileReadWrite,Number) => Async[Bytes,Error]
    native 'file-read';
export function write:
    &(FileWriteOnly,Bytes) => Async[unit,Error]
    native 'file-write';
export function write:
    &(FileReadWrite,Bytes) => Async[unit,Error]
    native 'file-write';

export function seek-start:
    &(File,Integer) => Async[Integer,Error]
    native 'file-seek-start';
export function seek-delta:
    &(File,Integer) => Async[Integer,Error]
    native 'file-seek-delta';
export function seek-end:
    &(File,Integer) => Async[Integer,Error]
    native 'file-seek-end';

export function read-char:
    &(FileReadOnly) => Async[Char,Error]
    native 'file-read-char';
export function read-char:
    &(FileReadWrite) => Async[Char,Error]
    native 'file-read-char';
export function write-char:
    &(FileWriteOnly,Char) => Async[unit,Error]
    native 'file-write-char';
export function write-char:
    &(FileReadWrite,Char) => Async[unit,Error]
    native 'file-write-char';

export function read-string:
    &(FileReadOnly) => Async[String,Error]
    native 'file-read-string';
export function read-string:
    &(FileReadWrite) => Async[String,Error]
    native 'file-read-string';
export function write-string:
    &(FileWriteOnly,String) => Async[unit,Error]
    native 'file-write-string';
export function write-string:
    &(FileReadWrite,String) => Async[unit,Error]
    native 'file-write-string';

export function read-line:
    &(FileReadOnly) => Async[String,Error]
    native 'file-read-line';
export function read-line:
    &(FileReadWrite) => Async[String,Error]
    native 'file-read-line';
export function write-line:
    &(FileWriteOnly,String) => Async[unit,Error]
    native 'file-write-line';
export function write-line:
    &(FileReadWrite,String) => Async[unit,Error]
    native 'file-write-line';

export function read-lines:
    &(FileReadOnly) => Observable[String,Error]
    native 'file-read-lines';
export function read-lines:
    &(FileReadWrite) => Observable[String,Error]
    native 'file-read-lines';

export function read-all:
    &(FileReadOnly) => Async[Bytes,Error]
    native 'file-read-all';
export function read-all:
    &(FileReadWrite) => Async[Bytes,Error]
    native 'file-read-all';
